#include "Scope.h"

#include "InCommentC.h"
#include "InCommentCPP.h"
#include "InGlobal.h"
#include "InParen.h"
#include "InBlock.h"
#include "InBracket.h"
#include "InPreProcessor.h"
#include "InLiteral.h"

#include<string>
#include<iostream>

using namespace std;

Scope::Scope()
{
    m_eType=Scope::eScopeInvalid;
    m_pxParent = NULL;
    m_asSubstream.push_back("");
    m_iSubstreamElement = 0;
}

Scope::~Scope()
{
}

//Do not call for Comment scope types
Scope* Scope::process(Token &inToken, bool &bIsEndOfScope)
{
    Scope* pxScope = NULL;
    char cDelimiter = char(inToken);
    
    //Check for comment; a comment can appear in any scope
    if (true==inToken.m_bIsDelimiter)
    {
        pxScope = detectComment(cDelimiter);
    }

    //Save the token
    m_asWorkspace.push_back(inToken.m_sValue);

    if(pxScope == NULL)
    //Check for new scope opening character, if not comment
    {
        switch(cDelimiter)
        {
        case '{':
            pxScope = new InBlock(this);
            break;

        case '(':
            pxScope = new InParen(this);
            break;

        case '[':
            pxScope = new InBracket(this);
            break;

        case '#':
            pxScope = new InPreProcessor(this);
            break;

        case '\'':
        case '"':
            pxScope = new InLiteral(this, cDelimiter);
            break;

        case '/':
        case ' ':
        case '\n':
        case '\r':
        case '\t':
            break;

        case ')':
        case '}':
        case ']':
            m_asSubstream[m_iSubstreamElement]=m_asSubstream[m_iSubstreamElement].substr(0, m_asSubstream[m_iSubstreamElement].size()-1);
            break;

        case ',':
        case ';':
            m_asSubstream[m_iSubstreamElement]=m_asSubstream[m_iSubstreamElement].substr(0, m_asSubstream[m_iSubstreamElement].size()-1);
            this->m_iSubstreamElement++;
            this->m_asSubstream.push_back("");
            break;

        default:
            m_asSubstream[m_iSubstreamElement] += inToken.m_sValue;
            m_asSubstream[m_iSubstreamElement]+= " ";
            break;
        }
    }

    if(pxScope != NULL)
    {
        m_apxChildren.push_back(pxScope);
    }
    return pxScope;
}

Scope* Scope::detectComment(char inDelimiter)
{
    Scope* pxCommentScope = NULL;
    Comment::Type eCommentType = m_xComment.detect(inDelimiter);

    switch(eCommentType)
    {
    case Comment::eStyleC:
        pxCommentScope = new InCommentC(this);
        break;

    case Comment::eStyleCPP:
        pxCommentScope = new InCommentCPP(this);
        break;
    }

    return pxCommentScope;
}

void Scope::dump()
{
    int nWorkspaceSize;
    int nWorkspaceLooper;
    int nChildLooper;
    string sTemp;

    nWorkspaceSize = (int)m_asWorkspace.size();

    nChildLooper=0;
    for(nWorkspaceLooper = 0; nWorkspaceLooper<nWorkspaceSize; nWorkspaceLooper++)
    {
        sTemp = m_asWorkspace[nWorkspaceLooper];
        if(sTemp == "")
        {
            m_apxChildren[nChildLooper]->dump();
            nChildLooper++;
        }
        cout<<sTemp;
    }



}



